package org.smart.framework.core.prox;

import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @author lyric
 * @version 1.0.0
 * @date 2017/2/11 21:49
 * @description 代理链
 */
public class ProxyChain {

    /** 目标类 */
    private final Class<?> targetClass;

    /** 目标对象 */
    private final Object targetObject;

    /** 目标方法 */
    private final Method targetMethod;

    /** 方法代理 */
    private final MethodProxy methodProxy;

    /** 方法参数 */
    private final Object[] methodParams;

    /** 代理索引 */
    private int index = 0;

    /** 代理列表 */
    private List<Proxy> proxies = new ArrayList<Proxy>();

    /**
     * @author lyric
     * @description 含参构造函数
     * @param targetClass 目标类
     * @param targetObject 目标对象
     * @param targetMethod 目标方法
     * @param methodProxy 方法代理
     * @param methodParams 方法参数
     * @param proxies 代理列表
     */
    public ProxyChain(Class<?> targetClass, Object targetObject, Method targetMethod, MethodProxy methodProxy, Object[] methodParams, List<Proxy> proxies) {
        this.targetClass = targetClass;
        this.targetObject = targetObject;
        this.targetMethod = targetMethod;
        this.methodProxy = methodProxy;
        this.methodParams = methodParams;
        this.proxies = proxies;
    }

    /**
     * @author lyric
     * @description 获得目标类
     * @return
     */
    public Class<?> getTargetClass() {
        return targetClass;
    }

    /**
     * @author lyric
     * @description 获得目标方法
     * @return
     */
    public Method getTargetMethod() {
        return targetMethod;
    }

    /**
     * @author lyric
     * @description 获得方法参数
     * @return
     */
    public Object[] getMethodParams() {
        return methodParams;
    }

    /**
     * @author lyric
     * @description 执行代理链
     * @return
     * @throws Throwable
     */
    public Object doProxyChain() throws Throwable {
        Object methodResult;
        if (index < proxies.size()) {
            methodResult = proxies.get(index++).doProxy(this);
        } else {
            methodResult = methodProxy.invokeSuper(targetObject, methodParams);
        }
        return methodResult;
    }
}
